package me.qin.miclock;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.Calendar;

/**
 * Created by qin on 2017/8/3.
 */

public class ClockView extends View {

    private Paint paint;
    private int width;
    private int height;
    private float fx;
    private float fy;
    private Camera camera;
    private Path path;
    private Calendar date;
    private float outerCircleRadius = 135;
    private float minuteHand = 70;
    private float secondHand = 115 + 4;
    private RectF rectF;
    private ValueAnimator animator;
    private float jumpValue;

    //123
    public ClockView(Context context) {
        this(context, null);
    }

    public ClockView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ClockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
        paint.setAntiAlias(true);

        camera = new Camera();
        path = new Path();
        rectF = new RectF();

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        canvas.drawColor(getResources().getColor(R.color.colorPrimary));
        canvas.translate(width / 2, height / 2);

        //得到当前时间
        date = Calendar.getInstance();
        float miniSecond = date.get(Calendar.MILLISECOND);
        float second = date.get(Calendar.SECOND) + miniSecond / 1000;
        float minute = date.get(Calendar.MINUTE) + second / 60;
        float hour = date.get(Calendar.HOUR_OF_DAY) + minute / 60;
        float rotateHour = 2 * 360 * hour / 24;
        float rotateMinute = 360 * minute / 60;
        float rotateSecond = 360 * second / 60;
        camera.save();
        Camera currentCamera = camera;
        //小圆点跳跃高度
        jumpValue = 10 * (0.5f - Math.abs(((second * 1000 % (60000 / 180f)) / (60000 / 180f) - 0.5f)));


        //绘制刻度
        diawDial(canvas, rotateSecond, currentCamera);

        //外表盘
        drawOutCircle(canvas, currentCamera);

        //秒针小圆点
        drawSecondPoint(canvas, rotateSecond, currentCamera);

        //分针
        drawMinutHand(canvas, rotateMinute, currentCamera);

        //时针
        drawHourHand(canvas, rotateHour, currentCamera);

        canvas.restore();
        camera.restore();
        invalidate();

    }

    private void drawHourHand(Canvas canvas, float rotateHour, Camera currentCamera) {
        canvas.save();
        currentCamera.save();
        currentCamera.rotate(-90 * fy, 90 * fx, -rotateHour);
        currentCamera.translate(0, 0, -40);
        currentCamera.applyToCanvas(canvas);
        paint.setColor(0x55ffffff);
        paint.setStrokeWidth(3);
        canvas.drawCircle(0, 0, 8, paint);
        path.reset();
        path.moveTo(-3f, -7.5f);
        path.lineTo(-1.5f, -minuteHand);
        rectF.set(-1.5f, -minuteHand - 1.5f, 1.5f, -minuteHand + 1.5f);
        path.arcTo(rectF, -180, 180);
        path.lineTo(3, -7.5f);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawPath(path, paint);
    }

    private void drawMinutHand(Canvas canvas, float rotateMinute, Camera currentCamera) {
        canvas.restore();
        canvas.save();
        currentCamera.rotate(-90 * fy, 90 * fx, -rotateMinute);
        currentCamera.translate(0, 0, -60);
        currentCamera.applyToCanvas(canvas);
        paint.setColor(Color.WHITE);
        path.reset();
        path.moveTo(-2.5f, -9.68f);
        path.lineTo(-1.5f, -minuteHand);
        rectF.set(-1.5f, -minuteHand - 1.5f, 1.5f, -minuteHand + 1.5f);
        path.arcTo(rectF, -180, 180);
        path.lineTo(2.5f, -9.68f);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawPath(path, paint);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        canvas.drawCircle(0, 0, 10, paint);
        canvas.restore();
        currentCamera.restore();
    }

    private void drawSecondPoint(Canvas canvas, float rotateSecond, Camera currentCamera) {
        canvas.save();
        currentCamera.save();
        paint.setAlpha(255);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        currentCamera.rotate(-90 * fy, 90 * fx, -rotateSecond + 180);
        currentCamera.applyToCanvas(canvas);
        canvas.drawCircle(0, secondHand + jumpValue, 4, paint);
        currentCamera.restore();
        currentCamera.save();
    }

    private void drawOutCircle(Canvas canvas, Camera currentCamera) {
        canvas.save();
        currentCamera.save();
        currentCamera.rotate(-90 * fy, 90 * fx, 0);
        currentCamera.translate(0, 0, 20);
        currentCamera.applyToCanvas(canvas);
        paint.setStrokeWidth(1);
        rectF.set(-outerCircleRadius, -outerCircleRadius, outerCircleRadius, outerCircleRadius);
        for (int i = 0; i < 4; i++) {
            canvas.drawArc(rectF, 5 + i * 90, 80, false, paint);
        }

        //时间数字
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(20);
        canvas.drawText("12", 0, -(outerCircleRadius - 8), paint);
        canvas.drawText("3", outerCircleRadius, 8, paint);
        canvas.drawText("6", 0, outerCircleRadius + 8, paint);
        canvas.drawText("9", -(outerCircleRadius), 8, paint);
        canvas.restore();
        currentCamera.restore();
    }

    private void diawDial(Canvas canvas, float rotateSecond, Camera currentCamera) {
        canvas.save();
        currentCamera.save();
        currentCamera.rotate(-90 * fy, 90 * fx, -((int) (rotateSecond + 180) / 2) * 2 - 2);
        currentCamera.applyToCanvas(canvas);
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        for (int i = 360; i > 0; i -= 2) {
            paint.setAlpha((int) (255 * ((1 - 0.5 * i / 120) > 0.5 ? (1 - 0.5 * i / 120) : 0.5)));
            canvas.drawLine(0, 100, 0, 115, paint);
            canvas.rotate(2);
        }
        canvas.restore();
        currentCamera.restore();
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        if (event.getAction() == MotionEvent.ACTION_DOWN && animator != null) {
            animator.cancel();
        }
        float offset = x - width / 2;
        fx = 2 * offset * 0.2f / width;
        float offset2 = y - height / 2;
        offset2 = Math.abs(offset2) > height / 2 ? height / 2 * (offset2 > 0 ? 1 : -1) : offset2;
        fy = 2 * offset2 * 0.2f / height;
        if (event.getAction() == MotionEvent.ACTION_UP) {
            doAnim();
        }
        return true;
    }

    private void doAnim() {
        final float startFx = fx;
        final float startFy = fy;
        animator = ValueAnimator.ofFloat(1, -0.5f, 0.5f, -0.25f, 0);
        animator.setDuration(1000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                fx = startFx * value;
                fy = startFy * value;
            }
        });
        animator.start();
    }

}
